package com.zllkj.mm.widgets;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

//流式布局
public class FlowLayout extends ViewGroup {

    public FlowLayout(Context context) {
        super(context);
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //重要:ViewGroup测量自身前要先测量所有子View宽高
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        //定义期望宽高
        int desiredWidth, desiredHeight = 0;
        //测量期望宽度
        if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {//若本View宽被设置确切值
            desiredWidth = MeasureSpec.getSize(widthMeasureSpec);//满足布局者想要多少给多少
        } else {//若本View宽被设置非确切值(wrap_content
            desiredWidth = getResources().getDisplayMetrics().widthPixels;//宽度设为屏幕宽度
        }
        //测量期望高度
        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {//若本View高被设置确切值
            desiredHeight = MeasureSpec.getSize(heightMeasureSpec);//满足布局者想要多少给多少
        } else {//若本View高被设置非确切值(wrap_content
            int currentLineWidth = 0;//当前行已占宽 (本行所有子View的宽之和,包括左右边距
            int currentLineHeight = 0;//当前行最大高 (取决于本行最高子View高度,包括上下间距
            for (int i = 0; i < getChildCount(); i++) {//遍历所有子View
                View child = getChildAt(i);
                MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();//方便获取左右Margin
                //当前行剩余宽<子View宽加左右边距(即放不下,准备换行,累加期望高,并清零重计下一行宽高
                if (getMeasuredWidth() - currentLineWidth < child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin) {
                    desiredHeight += currentLineHeight;//累加到期望高
                    currentLineWidth = 0;
                    currentLineHeight = 0;
                }
                currentLineWidth += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;//当前行累加子View宽(包括Margin
                currentLineHeight = Math.max(currentLineHeight, child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);//自检当前行最大高
            }
            desiredHeight += currentLineHeight;//最后一个子View放下,当前行高累加到期望高
        }
        //设置期望宽高
        setMeasuredDimension(desiredWidth, desiredHeight);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int currentLineWidth = l;//当前行已占宽 (本行所有子View的宽之和,包括左右边距
        int totalHeight = t;//之前所有行的总高度(包括上下边距);
        int currentLineHeight = 0;//当前行最大高 (取决于本行最高子View高度,包括上下间距
        for (int i = 0; i < getChildCount(); i++) {//遍历所有子View
            View child = getChildAt(i);
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();//方便获取左右Margin
            //当前行剩余宽<子View宽加左右边距(即放不下,准备换行,累加总行高,并清零重计下一行宽高
            if (getMeasuredWidth() - currentLineWidth < child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin) {
                totalHeight += currentLineHeight;//累加总行高
                currentLineWidth = l;
                currentLineHeight = 0;
            }
            //插入子View
            int left = currentLineWidth + lp.leftMargin;
            int right = left + child.getMeasuredWidth();
            int top = totalHeight + lp.topMargin;
            int bottom = top + child.getMeasuredHeight();
            child.layout(left, top, right, bottom);

            currentLineWidth += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;//当前行累加子View宽(包括Margin
            currentLineHeight = Math.max(currentLineHeight, child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);//自检当前行最大高
        }
//        totalHeight += currentLineHeight;//最后一个子View放下,当前行高累加到总行高
    }

    @Override//(MarginLayoutParams) child.getLayoutParams()
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }
}
